package com.own.component.log.login.core.impl;

import com.own.component.log.login.core.PersistenceLogLoginHook;
import com.own.component.log.login.em.LogLoginStatusEnum;
import com.own.component.log.login.entity.LogLoginEntity;
import com.own.component.log.login.entity.LoginLastFailInfoEntity;
import com.own.component.log.login.util.LoginLimitRuleUtil;
import com.own.component.store.core.Store;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.time.Duration;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

/**
 * CoreDefaultAfterLogLoginHookImpl
 *
 * @author chenxueli
 * @date 2023-07-31 21:34:00
 */
@Slf4j
@Component
public class CoreDefaultAfterLogLoginHookImpl implements PersistenceLogLoginHook {

    @Resource
    private Store<String> store;

    @Resource
    private LoginLimitRuleUtil loginLimitRuleUtil;

    /**
     * 执行方法
     *
     * @param entity 日志信息
     */
    @Override
    public void run(LogLoginEntity entity) {
        // 记录错误的次数
        if (LogLoginStatusEnum.SUCCESS.equals(entity.getStatus())) {
            clear(entity.getLoginAccount(), entity.getLoginType());
            return;
        }
        var ruleList = loginLimitRuleUtil.get(entity.getLoginType());
        if (ruleList == null) {
            return;
        }
        var countKey = buildCountKey(entity.getLoginAccount(), entity.getLoginType());
        var timeKey = buildTimeKey(entity.getLoginAccount(), entity.getLoginType());
        // 设置缓存信息
        var count = store.atomic().incrementAndGet(countKey);
        for (var rule : ruleList) {
            if (count >= rule.getMaxFailCount()) {
                var duration = Duration.ofSeconds(rule.getLockTime());
                store.atomic().expire(countKey, duration);
                // 存入最后一次的时间
                store.value().set(timeKey, entity.getLoginTime().format(DateTimeFormatter.ISO_DATE_TIME), duration);
                return;
            }
        }
        // 设置默认的存储时间
        var duration = Duration.ofHours(6L);
        store.atomic().expire(countKey, duration);
        store.value().set(timeKey, entity.getLoginTime().format(DateTimeFormatter.ISO_DATE_TIME), duration);
    }

    /**
     * 根据用户id查询最后一次成功的登录日志信息
     *
     * @param account 用户账号
     * @param type    登录类型
     * @return 最后一次成功的登录日志信息
     */
    public LoginLastFailInfoEntity lastLoginTime(String account, String type) {
        var countKey = buildCountKey(account, type);
        var dateTimeText = store.value().get(buildTimeKey(account, type));
        if (!store.atomic().contains(countKey) || StringUtils.isBlank(dateTimeText)) {
            return LoginLastFailInfoEntity.NONE;
        }
        var count = store.atomic().get(countKey);
        var dateTime = LocalDateTime.parse(dateTimeText, DateTimeFormatter.ISO_DATE_TIME);
        return new LoginLastFailInfoEntity((int) count, dateTime);
    }

    private String buildCountKey(String account, String type) {
        return "llc:" + type + ":" + account;
    }

    private String buildTimeKey(String account, String type) {
        return "llt:" + type + ":" + account;
    }

    /**
     * 清除账号的登录错误缓存信息
     *
     * @param account 账号信息
     * @param type    登录类型信息
     */
    private void clear(String account, String type) {
        store.atomic().remove(buildCountKey(account, type));
        store.value().remove(buildTimeKey(account, type));
    }

}
